package com.ktwlsoft.archivemanage.domain.business.businessService;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.ktwlsoft.archivemanage.config.exception.ResultException;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.AccountRepositoryService;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.ArchiveUnitRepositoryService;
import com.ktwlsoft.archivemanage.domain.business.repositoryService.ImgsService;
import com.ktwlsoft.archivemanage.domain.dao.entity.Account;
import com.ktwlsoft.archivemanage.domain.dao.entity.ArchiveUnit;
import com.ktwlsoft.archivemanage.domain.dao.entity.Imgs;
import com.ktwlsoft.archivemanage.payload.Result;
import com.ktwlsoft.archivemanage.payload.ResultType;
import com.ktwlsoft.archivemanage.payload.basic.BaseSettingModifyRequest;
import com.ktwlsoft.archivemanage.payload.basic.ResetPasswordRequest;
import com.ktwlsoft.archivemanage.payload.basic.RetrievePasswordByPhoneRequest;
import com.ktwlsoft.archivemanage.payload.basic.VerificationCodeRequest;
import com.ktwlsoft.archivemanage.service.utils.PassWordUtils;
import com.ktwlsoft.archivemanage.service.utils.RedisUtil;
import com.ktwlsoft.archivemanage.service.utils.UserUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;

/**
 * 个人设置
 *
 * @author zhuhe on 2019/10/25 10:26
 * @version 1.0
 */
@Component
public class PersonalSettingsService {

    /**账号*/
    private final AccountRepositoryService accountRepositoryService;

    private final RedisUtil redisUtil;

    private final  PasswordEncoder passwordEncoder;

    private final AuthenticationManager authenticationManager;

    private final ImgsService imgsService;

    /**立档单位*/
    private final ArchiveUnitRepositoryService archiveUnitService;

    public PersonalSettingsService(AccountRepositoryService accountRepositoryService, RedisUtil redisUtil, PasswordEncoder passwordEncoder, AuthenticationManager authenticationManager, ImgsService imgsService, ArchiveUnitRepositoryService archiveUnitService) {
        this.accountRepositoryService = accountRepositoryService;
        this.redisUtil = redisUtil;
        this.passwordEncoder = passwordEncoder;
        this.authenticationManager = authenticationManager;
        this.imgsService = imgsService;
        this.archiveUnitService = archiveUnitService;
    }

    /**
      * 基本设置详情 on 2019/10/25 10:33
      *
      * @param id id
      * @return Result<?>
      */
    public Result<?> baseSettingDetail(Long id){
        Account account = accountRepositoryService.getById(id);
        if(account == null){
            return Result.body(id, ResultType.CHECK_ERROR).withMessage("该数据不存在");
        }
        //保留为null的字段
        JSONObject jsonObject = JSONObject.parseObject(JSON.toJSONString(account, SerializerFeature.WriteMapNullValue));
        Imgs imgs = new Imgs();
        imgs.setBusinessId(account.getId());
        imgs.setBusinessType("PROFILE");
        jsonObject.put("profile",imgsService.getByBusinessIdAndBusinessType(imgs));
        Imgs imgs1 = new Imgs();
        imgs1.setBusinessId(account.getId());
        imgs1.setBusinessType(account.getIdentityType());
        jsonObject.put("identityFile",imgsService.getByBusinessIdAndBusinessType(imgs1));
        return Result.ok(jsonObject);
    }

    /**
      * 基本设置修改 on 2019/10/25 10:50
      *
      * @param request request
      * @return Result<?>
      */
    public Result<?> baseSettingModify(BaseSettingModifyRequest request){
        Account account = new Account();
        account.setId(null);
        BeanUtils.copyProperties(request,account);
        account.setCreatedAt(null);
        account.setCreator(null);
        account.setCreatorId(null);
        //证件上传
        if(request.getIdentityFile() != null && request.getIdentityFile().size() > 0){
            //删除
            ImgUploadService.deleteByBIdAndBType(account.getId(),account.getIdentityType());
            if(request.getIdentityType() == null){
                return Result.body(null,ResultType.CHECK_ERROR).withMessage("证件类型不能为空");
            }
            ImgUploadService.imgUploads(request.getIdentityFile(), String.valueOf(account.getId()), request.getIdentityType());
        }
        //头像上传
        if(request.getProfileFile() != null) {
            //删除
            ImgUploadService.deleteByBIdAndBType(request.getId(),"PROFILE");
            //上传
            List<MultipartFile> multipartFiles = Lists.newArrayList();
            multipartFiles.add(request.getProfileFile());
            List<Imgs> imgss = ImgUploadService.imgUploads(multipartFiles, String.valueOf(account.getId()), "PROFILE");
            if (imgss != null && imgss.size() > 0) {
                account.setProfile(String.valueOf(imgss.get(0).getId()));
            }
        }
        try {
            accountRepositoryService.update(account);
        }catch (Exception e){
            e.printStackTrace();
            return Result.body(request, ResultType.UPDATE_ERROR);
        }
        return Result.ok(account);
    }

    /**
     * 修改密码 on 2019/10/24 17:54
     *
     * @param request request
     * @return Result<?>
     */
    public Result<?> modifyPassword(ResetPasswordRequest request){
        Account account = accountRepositoryService.getByUserName(request.getAccount());
        if(account == null){
            return Result.body(request, ResultType.CHECK_ERROR).withMessage("该用户不存在");
        }
        if(!passwordEncoder.matches(request.getOidPassword(),account.getPassword())){
            return Result.body(request, ResultType.CHECK_ERROR).withMessage("旧密码输入不正确");
        }
        if(!request.getNewPassword().equals(request.getRepeatNewPassword())){
            return Result.body(request, ResultType.CHECK_ERROR).withMessage("重复新密码输入不正确");
        }
        if(!PassWordUtils.checkPasswordIsStrong(request.getNewPassword())){
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("密码不能为空并且密码长度不小于8位数,包含小写字母,大写字母,数字和特殊字符");
        }
        account.setPassword(passwordEncoder.encode(request.getNewPassword()));
        account.setPasswordStrength(UserUtils.testingPasswordStrength(request.getNewPassword()));
        try {
            accountRepositoryService.update(account);
        }catch (Exception e){
            e.printStackTrace();
            return Result.body(request, ResultType.UPDATE_ERROR);
        }
        return Result.body(null,ResultType.BUSINESS_SUCCESS);
    }

    /**
      * 修改手机号 on 2019/10/25 14:30
      *
      * @param codePojo codePojo
      * @return Result<?>
      */
    public Result<?> updatePhone(VerificationCodeRequest codePojo){
        if(codePojo.getUserId() == null || codePojo.getUserId() <= 0){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("用户id为空");
        }
        if(codePojo.getLoginPassword() == null || "".equals(codePojo.getLoginPassword().trim())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("登录密码为空");
        }
        if(codePojo.getNewPhone() == null || "".equals(codePojo.getNewPhone().trim())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("新手机号为空");
        }
        if(codePojo.getVerificationCode() == null || "".equals(codePojo.getVerificationCode().trim())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("验证码为空");
        }
        Account user = accountRepositoryService.getById(codePojo.getUserId());
        if(user == null){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("该用户不存在");
        }
        if(user.getPassword() == null){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("获取不到该用户密码");
        }
        //校验密码
        if(!passwordEncoder.matches(codePojo.getLoginPassword(),user.getPassword())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("密码不正确");
        }
        //校验验证码
        JSONObject object = getCode(String.valueOf(codePojo.getUserId()));
        if(!object.getBoolean("state")){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage(object.getString("message"));
        }
        if(!object.getString("data").equals(codePojo.getVerificationCode())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("验证码不正确");
        }
        user.setTeleNum(codePojo.getNewPhone());
        try {
            accountRepositoryService.update(user);
        }catch (Exception e){
            e.printStackTrace();
            return Result.body(null,ResultType.UPDATE_ERROR);
        }
        //删除验证码
        deleteCode(String.valueOf(user.getId()));
        return Result.body("操作成功", ResultType.BUSINESS_SUCCESS);
    }

    /**
      * 修改邮箱 on 2019/10/25 14:51
      *
      * @param codePojo codePojo
      * @return Result<?>
      */
    public Result<?> updateMail(VerificationCodeRequest codePojo){
        if(codePojo.getUserId() == null || codePojo.getUserId() <= 0){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("用户id为空");
        }
        if(codePojo.getPhone() == null || "".equals(codePojo.getPhone().trim())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("手机号为空");
        }
        if(codePojo.getVerificationCode() == null || "".equals(codePojo.getVerificationCode().trim())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("验证码为空");
        }
        if(codePojo.getNewMail() == null || "".equals(codePojo.getNewMail().trim())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("新邮箱为空");
        }
        Account user = accountRepositoryService.getById(codePojo.getUserId());
        if(user == null){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("获取不到该用户");
        }
        if(user.getTeleNum() == null || "".equals(user.getTeleNum().trim())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("获取不到该用户手机号");
        }
        if(!user.getTeleNum().equals(codePojo.getPhone())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("手机号不正确");
        }
        //校验验证码
        JSONObject object = getCode(String.valueOf(user.getId()));
        if(!object.getBoolean("state")){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage(object.getString("message"));
        }
        if(!object.getString("data").equals(codePojo.getVerificationCode())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("验证码不正确");
        }
        user.setEmail(codePojo.getNewMail());
        try {
            accountRepositoryService.update(user);
        }catch (Exception e){
            e.printStackTrace();
            return Result.body(null,ResultType.UPDATE_ERROR);
        }
        //删除验证码
        deleteCode(String.valueOf(user.getId()));
        return Result.body(null,ResultType.BUSINESS_SUCCESS);
    }

    /**
      * 通过手机号找回密码 on 2019/10/31 11:57
      *
      * @param request request
      * @param type 1.用户端,2.管理端
      * @return Result<?>
      */
    @Transactional(rollbackFor = Exception.class)
    public Result<?> retrievePasswordByPhone(RetrievePasswordByPhoneRequest request,int type){
        Account checkUnique = new Account();
        checkUnique.setTeleNum(request.getPhone());
        if(type == 1) {
            checkUnique.setRoleName("立档单位");
        }else if(type == 2){
            checkUnique.setRoleName("管理");
        }
        List<Account> accounts = accountRepositoryService.checkUnique(checkUnique);
        if(accounts == null || accounts.size() <= 0){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("该账号不存在");
        }
        if(accounts.size() > 1){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("该手机号存在复数账号");
        }
        Account account = accounts.get(0);
        //校验验证码
        if(request.getVerificationCode() == null || "".equals(request.getVerificationCode().trim())) {
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("验证码不能为空");
        }
        JSONObject object = getCode(String.valueOf(request.getPhone()));
        if (!object.getBoolean("state")) {
            return Result.body(null, ResultType.CHECK_ERROR).withMessage(object.getString("message"));
        }
        if (!object.getString("data").equals(request.getVerificationCode())) {
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("验证码不正确");
        }
        if(!request.getNewPassword().equals(request.getRepeatNewPassword())){
            return Result.body(null,ResultType.CHECK_ERROR).withMessage("两次输入密码不一致");
        }
        if(!PassWordUtils.checkPasswordIsStrong(request.getNewPassword())){
            return Result.body(null, ResultType.CHECK_ERROR).withMessage("密码不能为空并且密码长度不小于8位数,包含小写字母,大写字母,数字和特殊字符");
        }
        account.setPassword(passwordEncoder.encode(request.getNewPassword()));
        try {
            accountRepositoryService.update(account);
            //同步修改立档单位密码
            ArchiveUnit archiveUnit = archiveUnitService.getByAccountId(account.getId());
            if(archiveUnit != null) {
                archiveUnit.setPassword(account.getPassword());
                archiveUnitService.update(archiveUnit);
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new ResultException(ResultType.UPDATE_ERROR.getReason(),ResultType.UPDATE_ERROR);
        }
        return Result.ok("");
    }

    /**
     * 从redis获取验证码 on 2019/5/17 16:32
     *
     * @param userId userId
     * @return JSONObject
     */
    private JSONObject getCode(String userId){
        JSONObject object = new JSONObject();
        String s = "";
        try {
            Object o = redisUtil.get(userId);
            if(o == null){
                object.put("state",false);
                object.put("message","验证码已超时");
                return object;
            }
            s = o.toString();
        }catch (Exception e){
            e.printStackTrace();
            object.put("state",false);
            object.put("message","Redis服务出现错误");
            return object;
        }
        object.put("state",true);
        object.put("data",s);
        return object;
    }

    private boolean deleteCode(String userId){
        try {
            redisUtil.delete(userId);
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
        return true;
    }
}